﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Configuration;
using System.Management;
using System.Collections;
// namespaces necesarios para conexión a bd
using System.Data;
using System.Data.Common;
using System.Data.SqlClient;
using System.Data.SqlTypes;

using System.ComponentModel;
using System.Drawing;
using System.Windows.Forms;

namespace Persistencia_y_capa_de_negocio
{
    /// <summary>
    /// CADUnidadesUsuario. Componente de acceso a la base de datos UsuariosUnidades.
    /// </summary>
    public class CADUnidadesUsuario
    {
        /// <summary>
        /// Representa una instancia de la clase.De forma que no he de crear
        /// una nueva cada vez.
        /// </summary>
        private static readonly CADUnidadesUsuario instancia = new CADUnidadesUsuario();
        /// <summary>
        /// Me permite obtener la variable privada instancia de la clase
        /// De esta forma siempre uso el mismo objeto que representa la clase.
        /// </summary>
        public static CADUnidadesUsuario Instancia
        {
            get { return instancia; }
        }
        /// <summary>
        /// Variable para almacenar la cadena de conexión
        /// </summary>
        private string cadCon;  // Cadena de conexión conseguida desde app.config
        private SqlDataAdapter da;
        private SqlConnection c;
        private DataSet vdb;


        /// <summary>
        /// Constructor por defecto de la clase CADUnidadesUsuario
        /// </summary>
        public CADUnidadesUsuario()
        {
            try
            {
                cadCon = ConfigurationManager.ConnectionStrings["conexion"].ConnectionString;

                c = new SqlConnection(cadCon);
            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.Message);
            }


        }


        /// <summary>
        /// Permite obtener la lista de unidades de un determinado usuario
        /// </summary>
        /// <param name="idUs">Id del usuario</param>
        /// <returns> Lista de objetos ENUnidadesUsuario que contienen las unidades del usuario</returns>
        public ArrayList obtenerUnidadesUsuario(int idUS)
        {
            vdb = new DataSet();
            da = new SqlDataAdapter("Select * from UsuariosUnidades where " + idUS.ToString() +
                                        "=usuario order by unidad asc", c);
            da.Fill(vdb, "UnidadesUsuario");
            ArrayList lista = new ArrayList();
            DataTable tabla = new DataTable();
            tabla = vdb.Tables["UnidadesUsuario"];

            foreach (DataRow fila in tabla.Rows)
            {
                ENUnidadesUsuario unus = new ENUnidadesUsuario();
                unus.IDUsuario = Convert.ToInt32(fila["usuario"]);
                unus.Cantidad = Convert.ToInt32(fila["cantidad"]);
                unus.IDUnidad = Convert.ToInt32(fila["unidad"]);

                lista.Add(unus);
            }
            return lista;
        }

        /// <summary>
        /// Devuelve la ENUnidadUsuario elegida
        /// </summary>
        /// <param name="idUs"></param>
        /// <param name="idEd"></param>
        /// <returns></returns>
        public ENUnidadesUsuario obtenerUnidadUsuario(int idUs, int idEd)
        {
            DataTable t = vdb.Tables["UnidadesUsuario"];
            ENUnidadesUsuario edu = new ENUnidadesUsuario();

            string select = "usuario = \'" + idUs.ToString() + " \' and unidad = \' " + idEd.ToString() + " \'";

            try
            {
                DataRow r = t.Select(select)[0];
                edu.IDUnidad = Convert.ToInt32(r["unidad"]);
                edu.IDUsuario = Convert.ToInt32(r["usuario"]);
                edu.Cantidad = Convert.ToInt32(r["cantidad"]);

            }
            catch
            {
            }

            return edu;
        }

        /// <summary>
        /// Permite dar de baja todas los unidades de un determinado usuario.
        /// </summary>
        /// <param name="iduser"> ID del usuario </param>
        public void DarDeBajaTodasUnidadesUsuario(int iduser)
        {
            string select;
            DataTable tabla = vdb.Tables["UnidadesUsuario"];
            DataRow[] filasEncontradas;

            select = "usuario = \'" + iduser.ToString() + "\'";

            try
            {
                //Obtengo una matriz de filas, con las fila en las que el campo coincide
                filasEncontradas = tabla.Select(select);
                //Recorro las filas encontradas y las voy borrando desde la ultima a la primera.
                for (int i = (filasEncontradas.Length - 1); i >= 0; i--)
                {
                    filasEncontradas[i].Delete();
                }
                SqlCommandBuilder command = new SqlCommandBuilder(da);
                da.Update(vdb, "UnidadesUsuario");
            }
            catch (Exception)
            {

                //No hay que hacer nada.
            }


        }

        /// <summary>
        /// Permite dar de baja una lista de unidades.
        /// </summary>
        /// <param name="listaid">Lista de objetos ENUnidadesUsuario que contienen las unidades</param>
        public void DarDeBajaUnidades(ArrayList listaid)
        {
            string select = "";
            DataTable tabla = vdb.Tables["UnidadesUsuario"];
            foreach (ENUnidadesUsuario unus in listaid)
            {
                select = "usuario = \'" + unus.IDUsuario.ToString() + "\' AND unidad = \'" + unus.IDUnidad.ToString() + "\'";               
                try
                {
                    DataRow fila = tabla.Select(select)[0];
                    fila.Delete();
                }
                catch (Exception)
                {

                    //No hay que hacer nada.
                }
            }
            SqlCommandBuilder command = new SqlCommandBuilder(da);
            da.Update(vdb, "UnidadesUsuario");
        }

        /// <summary>
        /// Permite dar de alta una lista de unidades.
        /// </summary>
        /// <param name="listaid">Lista de objetos ENUnidadesUsuario que contienen las unidades</param>
        public void DarDeAltaUnidades(ArrayList listaid)
        {
            string select;
            DataTable tabla = vdb.Tables["UnidadesUsuario"];
            foreach (ENUnidadesUsuario unus in listaid)
            {
                select = "usuario = \'" + unus.IDUsuario.ToString() + "\' AND unidad = \'" + unus.IDUnidad.ToString() + "\'";
                try
                {
                    DataRow fila = tabla.Select(select)[0];
                }
                catch (Exception)
                {
                    //Tengo que añadirlo pues no esta.
                    DataRow fila = tabla.NewRow();
                    fila["usuario"] = unus.IDUsuario;
                    fila["unidad"] = unus.IDUnidad;
                    fila["cantidad"] = unus.Cantidad;

                    tabla.Rows.Add(fila);
                }
            }
            SqlCommandBuilder command = new SqlCommandBuilder(da);
            da.Update(vdb, "UnidadesUsuario");
        }

        /// <summary>
        /// Incrementa el número de unidades del tipo indicado al usuario indicado
        /// </summary>
        /// <param name="idUsuario">Usuario al que añadir las unidades</param>
        /// <param name="idUnidad">Unidad que hay que aumentar</param>
        /// <param name="cantidad">Cantidad a aumentar</param>
        public void AnadirNumUnidadesUsuario(int idUsuario, int idUnidad, int cantidad)
        {
            ArrayList lista = obtenerUnidadesUsuario(idUsuario);

            // Lista que usamos para eliminar o anadir enunidadesUsuario.
            ArrayList listaAuxiliar = new ArrayList();

            bool anadido = false;
            if (lista.Count == 0)
            {
                // Significa que no tiene ninguna unidad y vamos a añadir la nueva
                ENUnidadesUsuario enu = new ENUnidadesUsuario();
                enu.Cantidad = cantidad;
                enu.IDUnidad = idUnidad;
                enu.IDUsuario = idUsuario;

                listaAuxiliar.Clear();
                listaAuxiliar.Add(enu);

                DarDeAltaUnidades(listaAuxiliar);
                // Una vez hecho esto, hemos añadido la unidad a la lista de unidades del usuario

                anadido = true;
            }
            else
            {
                foreach (ENUnidadesUsuario un in lista)
                {
                    if (un.IDUnidad == idUnidad)
                    {
                        un.Cantidad += cantidad;

                        listaAuxiliar.Clear();
                        listaAuxiliar.Add(un);
                        DarDeBajaUnidades(listaAuxiliar);

                        listaAuxiliar.Clear();
                        listaAuxiliar.Add(un);
                        DarDeAltaUnidades(listaAuxiliar);
                        //Ahora hemos eliminado la fila anticuada y la hemos vuelto a añadir con los datos actualizados.

                        anadido = true;
                    }
                }

                if (anadido == false)
                {
                    // Significa que inicialmente no teníamos ninguna unidad de este tipo. Tendremos que añadirla nosotros.
                    ENUnidadesUsuario enu = new ENUnidadesUsuario();
                    enu.Cantidad = cantidad;
                    enu.IDUnidad = idUnidad;
                    enu.IDUsuario = idUsuario;

                    listaAuxiliar.Clear();
                    listaAuxiliar.Add(enu);

                    DarDeAltaUnidades(listaAuxiliar);
                    // Una vez hecho esto, hemos añadido la unidad a la lista de unidades del usuario

                    anadido = true;
                }
            }
        }
    }
}
